import axios, {AxiosResponse, InternalAxiosRequestConfig} from "axios";
import {useUserStoreHook} from "@/store/modules/user";
import {ResultEnum} from "@/enums/ResultEnum";
import {F_FLAG_ENCRYPT, F_KEY_ENCRYPT, TOKEN_KEY, X_KEY_SM2} from "@/enums/CacheEnum";
import {decryptBySM4, doEncryptBySM2, doEncryptBySM4, genSm4Key} from "@/utils/smUtils";
import router from "@/router";
import {isJSON} from "@/utils/common";
import {useRequestStore} from "@/store";

// 创建 axios 实例
const service = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API,
    // baseURL: "/",
    timeout: 50000,
});
const URL_SM4KEY_MAP = 'URL-SM4KEY-PRE';
const loginPath = '/login'
const ENABLE_REQUEST_ENCRYPT = import.meta.env.VITE_ENABLE_REQUEST_ENCRYPT
// const ENABLE_REQUEST_ENCRYPT = false
export const deepCopy = (val: any): any => {
    return JSON.parse(JSON.stringify(val))
}

function containsFile(formData: FormData) {
    if (!(formData instanceof FormData) || typeof formData.entries !== 'function') {
        return false;
    }
    for (const [key, value] of formData.entries()) {
        if (value instanceof File) {
            return true;
        }
    }
    return false;
}

// 请求拦截器
service.interceptors.request.use(
    (config: InternalAxiosRequestConfig) => {
        const requestStore = useRequestStore();
        requestStore.setRequestPending(true);

        const accessToken = sessionStorage.getItem(TOKEN_KEY);
        // const accessToken = sessionStorage.getItem(TOKEN_KEY);
        if (accessToken) {
            config.headers[TOKEN_KEY] = accessToken;
        }
        let url: string = config?.url || ''
        let method = (config.method || '').toLowerCase();
        let data = config.data;
        let needTransToForm = isJSON(data) && method === 'post'

        if (needTransToForm) {
            const formData = new FormData();
            for (let d in data) {
                if ((data[d]?.toString().trim() || data[d] === 0) && !(Array.isArray(data[d]) && data[d].length === 0)) {
                    formData.append(d, data[d]);
                }
            }
            config.data = formData
            config.headers['Content-Type'] = 'multipart/form-data;';
        }

        //参数data为空时，也可以加密  处理data为{}的情况
        // if ((needTransToForm || !data || Object.keys(data).length <= 0) && ENABLE_REQUEST_ENCRYPT && url.indexOf("login") === -1) {
        if (ENABLE_REQUEST_ENCRYPT && url.indexOf("login") === -1 && !containsFile(config.data as FormData)) {
            let sm2Key = sessionStorage.getItem(X_KEY_SM2) || '';

            let sm4Key = genSm4Key();
            sessionStorage.setItem(URL_SM4KEY_MAP + url, sm4Key);
            let sm4KeyAfterSm2Encrypt = doEncryptBySM2(sm2Key, sm4Key);
            config.headers[F_KEY_ENCRYPT] = sm4KeyAfterSm2Encrypt;
            config.headers[F_FLAG_ENCRYPT] = true;

            if (data) {
                config.data = doEncryptBySM4(JSON.stringify(data), sm4Key)
                config.headers['Content-Type'] = 'text/plain;charset=UTF-8';
            }
        }
        return config;
    },
    (error: any) => {
        const requestStore = useRequestStore();
        requestStore.setRequestPending(false);
        return Promise.reject(error);
    }
);

// 响应拦截器
service.interceptors.response.use(
    async (response: AxiosResponse): Promise<any> => {
        const requestStore = useRequestStore();
        requestStore.setRequestPending(false);

        let url: string = response?.config?.url || ''
        if (url && url.indexOf("/logout") !== -1) {
            return response;
        }

        let contentType: any
        let filename: any

        if (response && response.headers && typeof response.headers.get === 'function') {
            contentType = response.headers.get('content-type');
            filename = response?.headers?.get('content-disposition')
        }
        if (contentType && contentType.toLowerCase().indexOf("noautodownload") !== -1) {
            return response
        }
        const isDownload = contentType && (contentType.indexOf("download") !== -1 || contentType.indexOf("ms-excel") !== -1
            || contentType.indexOf("octet-stream") !== -1 || contentType.indexOf("force-download") !== -1 || contentType.indexOf("x-msdownload") !== -1);
        if (((filename || isDownload) && contentType.indexOf("json") === -1)) {
            filename = decodeURIComponent(filename.split("filename=")[1]);

            let downloadKey = Math.random() * 10000;
            let downloadStatus: { [key: number]: boolean } = (window.parent as any).downloadStatus || {}
            downloadStatus[downloadKey] = true as boolean

            (window.parent as any).downloadStatus = downloadStatus as any

            const blob = new Blob([response.data], {type: contentType});
            const downloadUrl = window.URL.createObjectURL(blob);

            const downloadLink = document.createElement("a");
            downloadLink.href = downloadUrl;
            downloadLink.download = filename;
            document.body.appendChild(downloadLink);
            downloadLink.click();
            document.body.removeChild(downloadLink);
            window.URL.revokeObjectURL(downloadUrl);
            return downloadKey
        }
        //下载文件出错时，即使类型为blob，后台依旧返回的是json
        if (response.data instanceof Blob && contentType.indexOf("json") !== -1) {
            return await (response.data as Blob).text().then((text => {
                if (text && isJSON(text)) {
                    let res = JSON.parse(text)
                    if (res?.encrypt && res?.data) {
                        let sm4keyPrefix = url.replace(window.location.origin, "")
                        const sm4Key = sessionStorage.getItem(URL_SM4KEY_MAP + sm4keyPrefix);
                        res.data = decryptBySM4(res.data, sm4Key);
                        res.data = JSON.parse(res.data);
                    }
                    if (res?.code === ResultEnum.RESPONSE_CODE_UN_LOGIN) {
                        ElMessage.error("用户登录过期，请重新登陆");
                        sessionStorage.removeItem(TOKEN_KEY);
                        const userStore = useUserStoreHook();
                        userStore.resetToken().then(() => {
                            router.push(loginPath);
                        });
                        return;
                    } else if (res?.code === ResultEnum.RESPONSE_CODE_FAILURE || res?.code === ResultEnum.RESPONSE_CODE_SYS_ERROR) {
                        const msg = res?.message?.substring(res.message.lastIndexOf(':') + 1) || res?.message;
                        ElMessage.error(msg);
                        return res;
                    } else if (res?.code === ResultEnum.RESPONSE_CODE_UNAUTHORIZED) {
                        ElMessage.error(res?.message || '系统错误');
                        return res;
                    } else if (!res?.status) {
                        ElMessage.error(res?.message || '操作失败!');
                        return res;
                    } else {
                        return res;
                    }
                }
            }))
        } else {
            let res = deepCopy(response.data);
            if (res?.encrypt && res?.data) {
                let sm4keyPrefix = url.replace(window.location.origin, "")
                const sm4Key = sessionStorage.getItem(URL_SM4KEY_MAP + sm4keyPrefix);
                res.data = decryptBySM4(res.data, sm4Key);
                res.data = JSON.parse(res.data);
                // response = res;
            }
            if (res?.code === ResultEnum.RESPONSE_CODE_UN_LOGIN) {
                ElMessage.error("用户登录过期，请重新登陆");
                sessionStorage.removeItem(TOKEN_KEY);
                const userStore = useUserStoreHook();
                userStore.resetToken().then(() => {
                    router.push(loginPath);
                });
                return;
            } else if (res?.code === ResultEnum.RESPONSE_CODE_SYS_ERROR) {
                const msg = res?.message?.substring(res.message.lastIndexOf(':') + 1) || res?.message;
                ElMessage.error(msg);
                return res;
            } else if (res?.code === ResultEnum.RESPONSE_CODE_UNAUTHORIZED) {
                ElMessage.error(res?.message || '系统错误');
                return res;
            } else if (!res?.status) {
                ElMessage.error(res?.message || '操作失败!');
                return res;
            } else {
                return res;
            }
        }
    }
    ,
    (error: any) => {
        const requestStore = useRequestStore();
        requestStore.setRequestPending(false);
        // 异常处理
        if (error.response.data) {
            const {code, msg} = error.response.data;
            if (code === ResultEnum.RESPONSE_CODE_UN_LOGIN) {
                ElMessageBox.confirm("当前页面已失效，请重新登录", "提示", {
                    confirmButtonText: "确定",
                    cancelButtonText: "取消",
                    type: "warning",
                }).then(() => {
                    const userStore = useUserStoreHook();
                    userStore.resetToken().then(() => {
                        router.push(loginPath);
                    });
                });
            } else {
                ElMessage.error(msg || "系统出错");
            }
        }
        return Promise.reject(error.message);
    }
)
;

// 导出 axios 实例
export default service;
